﻿/*
 * EventDispenser.h
 */

#ifndef __GDK_EVENTDISPENSER_H__
#define __GDK_EVENTDISPENSER_H__


#include <gdk/core/Types.h>
#include <gdk/core/Callback.h>
#include <gdk/core/Event.h>
#include <gdk/core/SharedPtr.h>

#include <list>
#include <map>
#include <algorithm>



namespace gdk
{



	class GDK_CORE_EXPORT EventHandler
	{
	public:
		typedef gdk::CallbackHandler<void, const Event *>  CallbackHandler;

	private:
		ClassId				_classId;
		CallbackHandler		_callback;

	public:
		__INLINE__ EventHandler(void)
		{
		}

		__INLINE__ EventHandler(const EventHandler &o)
			: _classId(o._classId)
			, _callback(o._callback)
		{
		}

		__INLINE__ const ClassId& getClassId(void) const
		{
			return _classId;
		}

		__INLINE__ const CallbackHandler& getCallbackHandler(void) const
		{
			return _callback;
		}

		__INLINE__ bool operator ==(const EventHandler &o) const
		{
			return _classId == o._classId
				&& _callback == o._callback;
		}
		__INLINE__ bool operator !=(const EventHandler &o) const
		{
			return !(this->operator ==(o));
		}
		__INLINE__ bool operator <(const EventHandler &o) const
		{
			return (_classId < o._classId)
				|| (_classId == o._classId && _callback < o._callback);
		}
		__INLINE__ bool operator >(const EventHandler &o) const
		{
			return (_classId > o._classId)
				|| (_classId == o._classId && _callback > o._callback);
		}
		__INLINE__ bool operator <=(const EventHandler &o) const
		{
			return !(this->operator >(o));
		}
		__INLINE__ bool operator >=(const EventHandler &o) const
		{
			return !(this->operator <(o));
		}

		__INLINE__ void operator ()(const Event *evt) const
		{
			return (_callback)(evt);
		}

		__INLINE__ void setNull(void)
		{
			return _callback.setNull();
		}

		__INLINE__ bool isNull(void) const
		{
			return _callback.isNull();
		}

		template<typename TyEvent>
		EventHandler(void(*func)(const TyEvent *))
			: _classId(TyEvent::getClassId_())
			, _callback(func)
		{
		}

		template<typename TyClass, typename TyEvent>
		EventHandler(const SharedPtr<TyClass> &obj, void(TyClass::*func)(const TyEvent *))
			: _classId(TyEvent::getClassId_())
			, _callback(obj, func)
		{
		}

		template<typename TyClass, typename TyEvent>
		EventHandler(TyClass *obj, void(TyClass::*func)(const TyEvent *))
			: _classId(TyEvent::getClassId_())
			, _callback(obj, func)
		{
		}

		template<typename TyClass, typename TyEvent>
		EventHandler(const gdk::Unknown::Handle_T<TyClass> &obj, void(TyClass::*func)(const TyEvent *))
			: _classId(TyEvent::getClassId_())
			, _callback(obj, func)
		{
		}

		template<typename TyClass, typename TyEvent>
		EventHandler(TyClass &obj, void(TyClass::*func)(const TyEvent *))
			: _classId(TyEvent::getClassId_())
			, _callback(obj, func)
		{
		}
	};


	class GDK_CORE_EXPORT EventDispenser
	{
	public:
		typedef EventHandler::CallbackHandler			CallbackHandler;

	private:
		typedef std::list<CallbackHandler>				EventHandlerList;
		typedef SharedPtr<EventHandlerList>				EventHandlerListPtr;
		typedef EventHandlerList::iterator				EventHandlerList_Iterator;
		typedef EventHandlerList::const_iterator		EventHandlerList_ConstIterator;
		typedef std::map<ClassId, EventHandlerListPtr>	EventHandlerMap;
		typedef EventHandlerMap::iterator				EventHandlerMap_Iterator;

	private:
		EventHandlerMap		_mapEventHandler;

	public:
		//----------------------------------------------------
		 void sendEvent(Event const *evt);
		//----------------------------------------------------
		bool addEventHandler(const EventHandler &o);
		void removeEventHandler(const EventHandler &o);
		//----------------------------------------------------
		void clear(void);
		//----------------------------------------------------
		/*
		void eraseEventHandler(ClassId classId)
		{
			EventHandlerMap_Iterator it = _mapEventHandler.find(classId);
			if (it != _mapEventHandler.end())
			{
				_mapEventHandler.erase(it);
			}
		}
		template<typename TyEvent>
		void eraseEventHandler(void)
		{
			eraseEventHandler(TyEvent::getClassId_());
		}
		*/
		//----------------------------------------------------
		template<typename TyEvent>
		bool addEventHandler(void(*func)(const TyEvent *))
		{
			return addEventHandler(EventHandler(func));
		}
		template<typename TyClass, typename TyEvent>
		bool addEventHandler(const SharedPtr<TyClass> &obj, void(TyClass::*func)(const TyEvent *))
		{
			return addEventHandler(EventHandler(obj, func));
		}
		template<typename TyClass, typename TyEvent>
		bool addEventHandler(TyClass *obj, void(TyClass::*func)(const TyEvent *))
		{
			return addEventHandler(EventHandler(obj, func));
		}
		template<typename TyClass, typename TyEvent>
		bool addEventHandler(TyClass &obj, void(TyClass::*func)(const TyEvent *))
		{
			return addEventHandler(EventHandler(obj, func));
		}
		template<typename TyClass, typename TyEvent>
		bool addEventHandler(const gdk::Unknown::Handle_T<TyClass> &obj, void(TyClass::*func)(const TyEvent *))
		{
			return addEventHandler(EventHandler(obj, func));
		}
		//----------------------------------------------------
		template<typename TyEvent>
		void removeEventHandler(void(*func)(const TyEvent *))
		{
			return removeEventHandler(EventHandler(func));
		}
		template<typename TyClass, typename TyEvent>
		void removeEventHandler(const SharedPtr<TyClass> &obj, void(TyClass::*func)(const TyEvent *))
		{
			return removeEventHandler(EventHandler(obj, func));
		}
		template<typename TyClass, typename TyEvent>
		void removeEventHandler(TyClass *obj, void(TyClass::*func)(const TyEvent *))
		{
			return removeEventHandler(EventHandler(obj, func));
		}
		template<typename TyClass, typename TyEvent>
		void removeEventHandler(TyClass &obj, void(TyClass::*func)(const TyEvent *))
		{
			return removeEventHandler(EventHandler(obj, func));
		}
		template<typename TyClass, typename TyEvent>
		void removeEventHandler(const gdk::Unknown::Handle_T<TyClass> &obj, void(TyClass::*func)(const TyEvent *))
		{
			return removeEventHandler(EventHandler(obj, func));
		}
		//----------------------------------------------------
		__INLINE__ EventDispenser& operator +=(const EventHandler &o)
		{
			addEventHandler(o);

			return *this;
		}
		__INLINE__ EventDispenser& operator -=(const EventHandler &o)
		{
			removeEventHandler(o);

			return *this;
		}
	};






}//namespace gdk




#endif //__GDK_EVENTDISPENSER_H__
